<template>
  <template v-if="!preview">
    <div
      class="zui-input"
      :class="{
        round,
        border: !hideBorder,
        disabled,
        'zui-input-large': size === 'large',
        'zui-input-small': size === 'small',
        multiline: multiline
      }"
    >
      <slot name="prefix"></slot>
      <input
        class="input"
        v-if="!autoHeight && !multiline"
        :style="inputStyle"
        :type="showPassword ? 'text' : type"
        :placeholder="placeholder"
        v-model="value"
        :maxlength="maxWordLength"
        :disabled="disabled"
        :readonly="readonly"
        @blur="$emit('blur')"
        ref="inputRef"
      />
      <textarea
        v-else
        class="textarea"
        :style="inputStyle"
        :type="type"
        :placeholder="placeholder"
        v-model="value"
        :rows="autoHeight ? 1 : lines"
        :disabled="disabled"
        :readonly="readonly"
        ref="textareaRef"
        @blur="$emit('blur')"
      ></textarea>
      <span v-if="showWordLimit" class="word-limit" :class="{ danger: maxReached }" :style="wordLimitPaddingStyle"
        ><span class="current">{{ !value ? 0 : String(value).length }}</span
        >/{{ maxWordLength }}</span
      >
      <span class="clear clickable" :style="clearCss" v-if="value && clearable" @click.stop="onClearTap">
        <i class="icon iconfont-zui icon-zui-clear"></i>
      </span>
      <div v-if="showEye" class="eye-wrap" @click="onEyeClick">
        <span
          v-if="type == 'password'"
          class="icon iconfont-zui"
          :class="{
            'icon-zui-eye': showPassword,
            'icon-zui-eye-slash': !showPassword
          }"
        ></span>
      </div>
      <slot name="suffix"></slot>
    </div>
  </template>
  <template v-else>
    <div class="zui-input preview">
      <span v-if="modelValue">{{ modelValue }}</span>
      <span v-else class="empty">未填写</span>
    </div>
  </template>
</template>
<script lang="ts" setup>
import { ref, computed, watch, CSSProperties, reactive, nextTick, onMounted } from 'vue'

const emit = defineEmits(['update:modelValue', 'blur'])

const props = defineProps({
  textAlign: {
    type: String,
    default: 'left'
  },
  // input 的 type 目前只支持 text、 number、password
  type: String,
  // 尺寸大小 small/(default)/large
  size: String,
  // 自动行高，true 时自动忽略 multiline 配置
  autoHeight: Boolean,
  // 多行显示
  multiline: Boolean,
  // 行高 默认3行
  lines: { type: Number, default: 3 },
  hideBorder: Boolean,
  round: Boolean,
  padding: { type: String, default: '6px 8px 6px 12px' },
  placeholder: String,
  modelValue: { type: [String, Number], default: '' },
  showWordLimit: Boolean,
  maxWordLength: {
    type: Number,
    default: 99999
  },
  clearable: Boolean,
  disabled: Boolean,
  readonly: Boolean,
  preview: Boolean,
  // 显示眼睛
  showEye: Boolean,
  autoFocus: Boolean
})

//***** 输入内容 *****/
const inputRef = ref()
const value = ref(props.modelValue)
watch(
  () => props.modelValue,
  (val) => {
    value.value = val
  }
)
watch(value, (val) => {
  emit('update:modelValue', val)
})

//***** 组件样式 *****/
const inputStyle: CSSProperties = {
  textAlign: props.textAlign,
  padding: props.padding
} as CSSProperties

const paddingRight = computed(() => {
  const paddingStyle = inputStyle.padding || '0'
  const paddings = paddingStyle.toString().split(' ')
  if (paddings.length == 4) {
    return paddings[1]
  } else if (paddings.length == 2) {
    return paddings[1]
  } else if (paddings.length == 1) {
    return paddings[0]
  }
  return '8px'
})

//***** 多行文本 (自动高度)*****/
const forceUpdateKey = ref(0)
const textareaRef = ref()
watch(value, (newVal, oldVal) => {
  if (oldVal == newVal) {
    return
  }
  if (props.autoHeight) {
    forceUpdateKey.value += 1
    nextTick(() => {
      changeTextareaHeight()
    })
  }

  function changeTextareaHeight() {
    if (!textareaRef.value) {
      return
    }
    var scrollHeight = textareaRef.value.scrollHeight
    var height = textareaRef.value.offsetHeight

    textareaRef.value.style.height = 'auto'
    // 最高 200 px
    textareaRef.value.style.height = Math.min(textareaRef.value.scrollHeight - 8, 200) + 'px'
    if (height <= scrollHeight) {
    }
  }
})

//***** 字数限制 *****/
const maxReached = computed(() => {
  return value.value && String(value.value).length >= props.maxWordLength
})

watch(value, (inputValue) => {
  if (maxReached.value) {
    value.value = String(inputValue).substring(0, props.maxWordLength)
  }
})

const wordLimitPaddingStyle = computed(() => {
  return {
    paddingLeft: '0px',
    paddingRight: value.value && props.clearable ? '0px' : paddingRight.value
  } as CSSProperties
})

//***** 清空 ******/
const clearCss: CSSProperties = {
  paddingLeft: '8px',
  paddingRight: paddingRight.value
} as CSSProperties

function onClearTap() {
  value.value = ''
}

//***** 眼睛 *****//
const showPassword = ref(false)
function onEyeClick() {
  showPassword.value = !showPassword.value
  console.log('showPassword.value :>> ', showPassword.value)
}

//***** 自动聚焦 *****//

onMounted(() => {
  if (props.autoFocus) {
    const dom = inputRef.value || textareaRef.value
    dom && dom.focus()
  }
})
</script>

<style lang="scss" scoped>
.zui-input {
  width: 100%;
  box-sizing: border-box;
  display: flex;
  background-color: #ffffff;
  box-sizing: border-box;
  transition: border 0.2s ease-out;
  .input {
    width: 100%;
    box-sizing: border-box;
    line-height: var(--zui-size-line-height-regular);
    &::placeholder {
      color: var(--zui-color-text-placeholder);
    }
  }
  .textarea {
    width: 100%;
    resize: none;
    line-height: var(--zui-size-line-height-regular);
    &::placeholder {
      color: var(--zui-color-text-placeholder);
    }
  }
  .word-limit {
    display: flex;
    align-items: center;
    color: var(--zui-color-text-placeholder);
    font-size: var(--zui-size-text-small);
    line-height: var(--zui-size-line-height-regular);
    &.danger {
      color: var(--zui-color-red);
    }
  }
  .clear {
    display: flex;
    align-items: center;
    color: var(--zui-color-text-placeholder);
    opacity: 0.6;
    .icon {
      font-weight: normal;
      font-size: var(--zui-size-text-large);
    }
  }
  .eye-wrap {
    display: flex;
    flex: none;
    width: 32px;
    align-items: center;
    text-align: left;
    cursor: pointer;
    .icon {
      color: var(--zui-color-text-secondary);
      font-size: 18px;
    }
  }
  &.zui-input-small {
    font-size: var(--zui-size-text-small);
    input {
      line-height: var(--zui-size-line-height-small);
      padding: 3px 12px;
    }
  }
  &.disabled {
    opacity: 0.5;
  }
  &.border {
    border: 1px solid var(--zui-color-border);
    &:not(.disabled):hover {
      border-color: var(--zui-color-primary);
    }
  }
  &.round {
    border-radius: var(--zui-size-border-radius-small);
  }
  &.preview {
    line-height: var(--zui-size-line-height-regular);
    border-radius: var(--zui-size-border-radius-small);
    padding: 6px 12px;
    background-color: var(--zui-color-fill-light);
    user-select: text;
    .empty {
      color: var(--zui-color-text-secondary);
    }
  }
  &.multiline {
    position: relative;
    .word-limit {
      right: 0;
      bottom: 0;
      position: absolute;
      background-color: #ffffff;
    }
  }
}
</style>
